using System;
using System.IO;

namespace AnTunes
{
	public class UnseekableStreamWrapper : Stream
	{
		public UnseekableStreamWrapper (Stream inner)
		{
			inner_ = inner;
			cache_ = new MemoryStream();
		}
		
		public override bool CanRead 
		{
			get 
			{
				return true;
			}
		}
		
		public override bool CanSeek 
		{
			get 
			{
				return true;
			}
		}
		
		public override bool CanWrite 
		{
			get 
			{
				return false;
			}
		}
		
		public override int Read (byte[] buffer, int offset, int count)
		{
			waitForDataReceived(cache_.Position + count);
			return cache_.Read(buffer, offset, count);
		}
		
		public override void Write (byte[] buffer, int offset, int count)
		{
			throw new NotImplementedException ();
		}
		
		public override void Flush ()
		{
			throw new NotImplementedException ();
		}
		
		public override void SetLength (long value)
		{
			throw new NotImplementedException ();
		}
		
		public override long Length 
		{
			get 
			{
				return cache_.Length;
			}
		}
		public override long Position 
		{
			get 
			{
				return cache_.Position;
			}
			set 
			{
				Seek(value, SeekOrigin.Begin);
			}
		}
		
		public override long Seek (long offset, SeekOrigin origin)
		{	
			if(origin==SeekOrigin.Begin)
			{
				waitForDataReceived(offset);
				return cache_.Seek(offset, origin);
			}
			else if(origin == SeekOrigin.Current)
			{
				waitForDataReceived(cache_.Position + offset);
				return cache_.Seek(offset, origin);
			}
			else
			{
				throw new NotImplementedException ();
			}
		}
		
		void waitForDataReceived(long targetLen)
		{
			const int chunkSize = 1024;
			byte[] data = new byte[chunkSize];
			long pos = cache_.Position;
			cache_.Position = cache_.Length;
			while(cache_.Length < targetLen)
			{
				int res = inner_.Read(data, 0, chunkSize);
				cache_.Write(data, 0, res);
			}
			cache_.Position = pos;
		}
			
		private Stream inner_;
		private Stream cache_;
	}
}

